﻿using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System;
using System.Data;
using System.Data.Odbc;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Globalization;

namespace Ruandao.Account
{
    using Ruandao.Account.EntityAccess;
    using System.Collections.Generic;
    using System.Data.Common;
    using System.Data.SqlClient;
    using Ruandao.HostServer;

    // 首先在配置项中直接指明了GroupCode和Title（服务器上部署的网件默认使用某组织的角色分类），
    // 可选的配置项RoleCategorySetter指出动态确定的角色分类。
    public sealed class RuandaoRoleProvider : RoleProvider
    {
        //RoleCategoryEntity roleCategory;

        /* 2012-5-22：！！！重大问题！！！
         * roleCategory不应该在Initialize中确定，而是在具体使用时才根据请求上下文来确定。
         */

        string roleCatalogTitle;
        string accountRoleSetter;

        //
        // System.Configuration.Provider.ProviderBase.Initialize Method
        //

        public override void Initialize(string name, NameValueCollection config)
        {
            //
            // Initialize values from web.config.
            //

            if (config == null)
                throw new ArgumentNullException("config");

            if (name == null || name.Length == 0)
                name = "RuandaoRoleProvider";

            if (String.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "Ruandao Role provider");
            }

            // Initialize the abstract base class.
            base.Initialize(name, config);

            roleCatalogTitle = config["defaultRoleCategory"];
            accountRoleSetter = config["defaultAccountContext"];

            //applicationName = string.Format("Title({0}),AccountContext({1})",title,roleCategory.AccountContextCode);
        }

        //// 应该使用缓存提升性能，按网站来缓存。
        //private RoleCategoryEntity GetRoleCategory()
        //{
        //    string account = "";
        //    if (!string.IsNullOrEmpty(accountRoleSetter))
        //    {
        //        IAccountRoleSetter setter = Activator.CreateInstance(Type.GetType(accountRoleSetter)) as IAccountRoleSetter;
        //        roleCatalogTitle = setter.RoleCategory;
        //        account = setter.AccountContextCode;
        //    }
        //    return RoleCategoryEntity.FetchByUIX_AccountContextCode_Tile(account, roleCatalogTitle);
        //}

        //
        // System.Web.Security.RoleProvider properties.
        //

        private string applicationName;


        public override string ApplicationName
        {
            get { return applicationName; }
            set { applicationName = value; }
        }

        //
        // System.Web.Security.RoleProvider methods.
        //

        //
        // RoleProvider.AddUsersToRoles
        //
        public override void AddUsersToRoles(string[] userNames, string[] roleNames)
        {
            List<int> roleIds = new List<int>();
            foreach (string r in roleNames)
            {
                roleIds.Add(
                    RoleEntity.FetchByWareName_LoweredRoleName(SiteWare.Current.Ware.WareName,r.ToLower()).Id);
            }
            foreach (int roleId in roleIds)
            {
                foreach (string u in userNames)
                {
                    Guid userGuid = RegisterUserEntity.FetchByLoweredName(u.ToLower()).Guid;
                    UsersInRolesEntity ur = new UsersInRolesEntity();
                    ur.RoleId = roleId;
                    ur.UserGuid = userGuid;
                    ur.Save();
                }
            }
        }
        //
        // RoleProvider.CreateRole
        //

        public override void CreateRole(string roleName)
        {
            if (roleName.Contains(","))
            {
                throw new ArgumentException("Role names cannot contain commas.");
            }
            if (RoleExists(roleName))
            {
                throw new SecurityException("所要创建的角色名已经存在。");
            }
            RoleEntity re = new RoleEntity();
            re.Name = roleName;
            re.LoweredName = roleName.ToLower();
            re.WareName = SiteWare.Current.Ware.WareName;
            re.Description = "";
            re.Save();

        }

        //
        // RoleProvider.DeleteRole
        //
        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            if (throwOnPopulatedRole && GetUsersInRole(roleName).Length > 0)
            {
                throw new SecurityException("Cannot delete a populated role.");
            }
            RoleEntity role = RoleEntity.FetchByWareName_LoweredRoleName(SiteWare.Current.Ware.WareName, roleName.ToLower());
            if (role == null)
            {
                throw new SecurityException("所要删除的角色名不存在。");
            }
            else
            {
                RoleEntity.Delete(role.Id);
                return true;
            }
        }

        //
        // RoleProvider.GetAllRoles
        //
        public override string[] GetAllRoles()
        {
            IList<RoleEntity> list = AccountAccess.GetInstance().SearchEntities<RoleEntity>("WHERE WareName='" + SiteWare.Current.Ware.WareName +"'");
            string[] roleNames = new string[list.Count];
            int i = 0;
            foreach (RoleEntity role in list)
            {
                roleNames[i++] = role.Name;
            }
            return roleNames;
        }

        //
        // RoleProvider.GetRolesForUser
        //
        public override string[] GetRolesForUser(string userName)
        {
            string cmd = "SELECT RoleName FROM ACT_UsersInRolesView WHERE WareName=@WareName AND LoweredUserName=@LoweredUserName";
            IDataReader reader = AccountAccess.GetInstance().GetDatabase().ExecuteReader(cmd,SiteWare.Current.Ware.WareName,userName.ToLower() );
            List<string> list = new List<string>();
            while (reader.Read())
            {
                list.Add(reader.GetString(reader.GetOrdinal("RoleName")));
            }
            return list.ToArray();
        }

        //
        // RoleProvider.GetUsersInRole
        //
        public override string[] GetUsersInRole(string roleName)
        {
            string cmd = "SELECT UserName FROM ACT_UsersInRolesView WHERE WareName=@WareName AND LoweredRoleName=@LoweredRoleName";
            IDataReader reader = AccountAccess.GetInstance().GetDatabase().ExecuteReader(cmd,SiteWare.Current.Ware.WareName,roleName.ToLower());
            List<string> list = new List<string>();
            while (reader.Read())
            {
                list.Add(reader.GetString(reader.GetOrdinal("UserName")));
            }
            return list.ToArray();
        }

        //
        // RoleProvider.IsUserInRole
        //
        public override bool IsUserInRole(string userName, string roleName)
        {
            string cmd = "SELECT UserName FROM ACT_UsersInRolesView WHERE WareName=@WareName AND LoweredRoleName=@LoweredRoleName AND LoweredUserName=@LoweredUserName";
            IDataReader reader = AccountAccess.GetInstance().GetDatabase().ExecuteReader(cmd, SiteWare.Current.Ware.WareName, roleName.ToLower(), userName.ToLower());
            if (reader.Read()) 
                return true;
            else 
                return false;
        }

        //
        // RoleProvider.RemoveUsersFromRoles
        //
        public override void RemoveUsersFromRoles(string[] userNames, string[] roleNames)
        {
            List<int> roleIds = new List<int>();
            foreach (string r in roleNames)
            {
                roleIds.Add(
                    RoleEntity.FetchByWareName_LoweredRoleName( SiteWare.Current.Ware.WareName, r.ToLower() ).Id );
            }
            foreach (int roleId in roleIds)
            {
                foreach (string u in userNames)
                {
                    Guid userGuid = RegisterUserEntity.FetchByLoweredName( u.ToLower()).Guid;
                    UsersInRolesEntity.Delete(userGuid, roleId);
                }
            }
        }

        //
        // RoleProvider.RoleExists
        //
        public override bool RoleExists(string roleName)
        {
            RoleEntity e = RoleEntity.FetchByWareName_LoweredRoleName(SiteWare.Current.Ware.WareName, roleName.ToLower());
            if (e == null)
                return false;
            else
                return true;
        }

        //
        // RoleProvider.FindUsersInRole
        //
        public override string[] FindUsersInRole(string roleName, string userNameToMatch)
        {
            string cmd = "SELECT UserName FROM ACT_UsersInRolesView WHERE WareName=@WareName AND LoweredRoleName=@LoweredRoleName AND UserName LIKE '%" + userNameToMatch + "%'";
            var list = AccountAccess.GetInstance().GetDatabase().SearchObjects(cmd, SiteWare.Current.Ware.WareName, roleName.ToLower());
            List<string> users = new List<string>();
            foreach( dynamic o in list )
            {
                users.Add( o.UserName.ToString() );
            }
            return users.ToArray();
        }

    }
}